package com.diaohw.platform.common.obj.thread;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.diaohw.platform.common.constant.RequestConstant;
import com.diaohw.platform.common.obj.Result;
import com.diaohw.platform.common.obj.log.RequestLog;
import com.diaohw.platform.common.util.JsonUtil;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.MDC;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.time.LocalDateTime;
import java.util.Optional;

import static com.diaohw.platform.common.constant.RequestConstant.*;


/**
 * @author 刁海文
 * @Remark request 请求工具类
 * @since 2023/6/28 21:09
 */
@Getter
@Setter
public class RequestThread {
    /**
     * 本机IP地址
     */
    public final static String LOCAL_IP = NetUtil.getLocalhostStr();
    /**
     * thread local
     */
    private final static ThreadLocal<RequestThread> threadLocal = new InheritableThreadLocal<>();
    /**
     * 请求日志
     */
    private RequestLog log;

    /**
     * 请求头携带的权限信息
     */
    private String authorization;

    /**
     * 是否启用操作日志
     */
    private boolean enable;

    /**
     * 是否记录请求数据
     */
    private boolean request;

    /**
     * 是否记录响应数据
     */
    private boolean response;


    /**
     * 初始化请求信息
     *
     * @param requestId     请求链路ID
     * @param linkId        默认为1
     * @param authorization 请求头携带的权限信息
     */
    public static RequestThread initializationBase(String requestId, String linkId, String authorization) {
        RequestLog requestLog = new RequestLog();
        requestLog.setApplicationName(SpringUtil.getApplicationName());
        requestLog.setApplicationIP(LOCAL_IP);
        requestLog.setRequestId(Optional.ofNullable(requestId).orElse(IdUtil.fastUUID().toUpperCase()));
        requestLog.setLinkId(Optional.ofNullable(linkId).map(Convert::toInt).orElse(1));
        requestLog.setRequestTime(LocalDateTime.now());
        RequestThread cache = new RequestThread();

        cache.authorization = authorization;
        cache.log = requestLog;
        // log日志的MDC
        MDC.put(REQUEST_ID, requestId);
        MDC.put(LINK_ID, linkId);
        MDC.put(IP, LOCAL_IP);
        threadLocal.set(cache);
        return cache;
    }


    /**
     * 自定义请求头
     */
    public static MultiValueMap<String, String> headers() {
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        RequestThread local = threadLocal.get();
        if (local == null) {
            return headers;
        }

        if (StrUtil.isNotBlank(local.authorization)) {
            headers.add(RequestConstant.AUTHORIZATION, local.authorization);
        }
        RequestLog log = local.log;
        if (log == null) {
            headers.add(RequestConstant.REQUEST_ID, IdUtil.fastUUID().toUpperCase());
            headers.add(RequestConstant.LINK_ID, "1");
            return headers;
        }

        headers.add(RequestConstant.REQUEST_ID, log.getRequestId());
        headers.add(RequestConstant.LINK_ID, Integer.toString(log.getLinkId() + 1));

        return headers;
    }

    /**
     * 设置存储request body
     *
     * @param requestBody 请求参数
     */
    public static void putRequestParameter(Object requestBody) {
        if (isRequest()) {
            threadLocal.get().log.setRequestData(JsonUtil.toJsonString(requestBody));
        }
    }

    /**
     * 存储入参
     *
     * @param method 请求方法 POST，GET。。。
     * @param uri    URL
     */
    public static void putRequestRemote(String method, String uri, Object requestBody) {
        if (isRequest()) {
            threadLocal.get().log.setRequestData(JsonUtil.toJsonString(requestBody));
        }
        threadLocal.get().log.setMethod(method);
        threadLocal.get().log.setUri(uri);
    }


    /**
     * 存储相应参数
     *
     * @param result 相应结果
     */
    public static void putResponseData(Result<?> result) {
        if (threadLocal.get() == null) {
            return;
        }
        if (isResponse()) {
            threadLocal.get().log.setResponseData(JsonUtil.toJsonString(result.getData()));
        }
        threadLocal.get().log.setResponseTime(LocalDateTime.now());
        threadLocal.get().log.computeElapsed();

        threadLocal.get().log.setStatus(result.getStatus());
        threadLocal.get().log.setMsg(result.getMsg());
    }


    /**
     * 请求链路ID
     */
    public static String getThreadRequestId() {
        return threadLocal.get().log.getRequestId();
    }

    /**
     * 链路编号
     */
    public static int getThreadLinkId() {
        return threadLocal.get().log.getLinkId();
    }

    /**
     * 权限token
     */
    public static String getThreadAuthorization() {
        return threadLocal.get().authorization;
    }

    /**
     * 操作日志
     */
    public static RequestLog getThreadLocal() {
        return threadLocal.get().log;
    }


    /**
     * 清除ThreadLocal
     */
    public static void clear() {
        threadLocal.remove();
        MDC.clear();
    }


    public static boolean isEnable() {
        return threadLocal.get().enable;
    }

    public static boolean isRequest() {
        return threadLocal.get().request;
    }

    public static boolean isResponse() {
        if (threadLocal.get() == null) {
            return Boolean.FALSE;
        }
        return threadLocal.get().response;
    }

    public static String getDescription() {
        return threadLocal.get().getLog().getDescription();
    }


}
